/*
Title: Bus Activity Monitor to Uart Testbench
Author: Rajas Mokashi
Created for: ECE510: System Verilog Final Project
Description: This is the Testbench used for testing Uart Port(module).
*/

module UARTTestbench();
  timeunit 1ns;
  timeprecision 1ns;
  
  parameter Clock_Width = 62ns;
  
  reg Clock, Recieve;
  wire Transmit, Error;
  integer file;
  int RandomTester,NumberOfTests;
  logic [7:0] RandomData = 0;
  logic Control = 0;
  
  BAMToUARTInterface BTUBus();
  UARTModule UARTModuleInstance(.FromBAM(BTUBus.UARTToBAM), .Clock(Clock), .Recieve(Recieve), .Transmit(Transmit), .Error(Error));
  
  initial
  begin
    Clock = 1'b0;        
//    $display("\t\tTime\t\tSent Data(Hex)\t\tSent Data\t\tRecieved Data\t\tParity Bit\n\n");
//    $monitor($time, "     %h      %b      %b      %b",BTUBus.TransmitData,BTUBus.TransmitData,BTUBus.RecieveData,UARTModuleInstance.ParityBit);
    forever #Clock_Width Clock = ~Clock;
  end
  
  task automatic UartLBTransactionTest(input bit [7:0] DataToTransmit, input bit ControlOrData);    // Loop Back Test i.e. Recieve = Trasmit
    bit [7:0] RecievedData;
    fork
    begin
      BTUBus.TransmitData = DataToTransmit;             // Make transmit transaction
      BTUBus.ControlOrData = ControlOrData;
      BTUBus.TransmitDataSent = 1'b1;
      @(posedge BTUBus.TransmitAcknowledge);
      BTUBus.TransmitDataSent = 1'b0;
    end
    begin
      if(ControlOrData==0)                              // Make recieve transaction
        begin
          wait(BTUBus.RecieveDataSent);
          @(negedge UARTModuleInstance.BaudClk);
          RecievedData = BTUBus.RecieveData;
          @(negedge UARTModuleInstance.BaudClk);
          BTUBus.RecieveAcknowledge = 1'b1;
          @(negedge UARTModuleInstance.BaudClk);
          BTUBus.RecieveAcknowledge = 1'b0;
        end
    end
    join
    if(ControlOrData==0)                                  // Check if recived data matches transmitted data
      begin
        if(UARTModuleInstance.ControlWord[6]==0)          // No parity bit
          begin
            if(DataToTransmit == RecievedData)            // Check full recieved byte
              $display("Transaction was successfull\n");
            else
              $display($time,"Error occured:\nSent Byte: %h\tRecieved Byte: %h",DataToTransmit,RecievedData);
          end
        else                                              // If parity used
          begin
            if(DataToTransmit[6:0] == RecievedData[6:0])  // Check only 7 bit of actual data
              $display("Transaction was successfull\n");
            else
              $display($time,"Error occured:\nSent Byte: %h\tRecieved Byte: %h",DataToTransmit,RecievedData);
          end
      end
      $fdisplay(file,"%h",RecievedData);
  endtask
  
  initial
  begin
    repeat (6) @(negedge Clock);
    assign UARTModuleInstance.Recieve = UARTModuleInstance.Transmit;     // Put design in loopback mode for testing
    NumberOfTests = 1000;
    file = $fopen("Recieve.txt","w");
    $display("File:%h",file);
    
    // All directed tests using parity check both odd and even number of 1's
    UartLBTransactionTest(8'h04,1'b1);    // One Stop Bit No Parity Baud = 9600
    UartLBTransactionTest(8'ha2,1'b0);    
    UartLBTransactionTest(8'h84,1'b0);
    UartLBTransactionTest(8'h49,1'b0);
    UartLBTransactionTest(8'hEB,1'b1);    // Two Stop Bit Even Parity Baud = 115200(Max Baud Rate)
    UartLBTransactionTest(8'h65,1'b0);
    UartLBTransactionTest(8'h34,1'b0);
    UartLBTransactionTest(8'hAA,1'b0);
    UartLBTransactionTest(8'hC2,1'b1);    // Two Stop Bit Odd Parity Baud = 300(Min Baud Rate)
    UartLBTransactionTest(8'hF0,1'b0);
    UartLBTransactionTest(8'h41,1'b0);
    UartLBTransactionTest(8'hFC,1'b0);
    
    // Random Tests
    for(RandomTester=0;RandomTester<NumberOfTests;RandomTester++)
    begin
      RandomData = $urandom;
      Control = ~Control;
      UartLBTransactionTest(RandomData,Control);  // Random Tests Call
    end
    repeat (6) @(negedge UARTModuleInstance.BaudClk);
    $fclose(file);
    $stop;
  end
  
endmodule
